﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using RG.Common.Configuration;
using ApplicationSettingsBase=RG.Common.Configuration.ApplicationSettingsBase;

namespace RG.Common.WPF.Settings
{
    public class WpfSettings : ApplicationSettingsBase
    {
        private static void CollectFromSaveProperty(ICollection<ISetting> collected, DependencyObject element)
        {
            var names = Collector.GetSave(element);
            if (string.IsNullOrEmpty(names))
                return;

            var elementName = element.GetValue(FrameworkElement.NameProperty) as String;
            if (!string.IsNullOrEmpty(elementName))
            {
                elementName = string.Concat(elementName, ".");
            }

            foreach (var propName in names.Split(new[] {';'}))
            {
                var propInfo = element.GetType().GetProperty(propName,
                                                             BindingFlags.Instance | BindingFlags.Public |
                                                             BindingFlags.NonPublic);

                if (propInfo == null)
                {
                    Debug.WriteLine(string.Format("WpfSettigns: не найдено свойство {0} в типе {1}", propName,
                                                  element.GetType().FullName));
                    continue;
                }

                var settingName = string.Concat(elementName, propName);
                collected.Add(new PropertySetting(settingName, element, propInfo, null, SettingsSerializeAs.String));
            }
        }

        private static void CollectFromPropertyProperty(ICollection<ISetting> collected, DependencyObject element)
        {
            var dp = Collector.GetProperty(element);
            if (dp == null)
                return;
            
            var elementName = element.GetValue(FrameworkElement.NameProperty) as String;
            if (!string.IsNullOrEmpty(elementName))
            {
                elementName = string.Concat(elementName, ".");
            }

            // TODO По хорошему надо сделать специальный DependencyPropertySetting, работать быстрее будет
            var propInfo = element.GetType().GetProperty(dp.Name,
                                             BindingFlags.Instance | BindingFlags.Public |
                                             BindingFlags.NonPublic);

            var settingName = string.Concat(elementName, dp.Name);
            collected.Add(new PropertySetting(settingName, element, propInfo, null, SettingsSerializeAs.String));
        }

        private static void CollectRecursive(ICollection<ISetting> collected, DependencyObject element)
        {
            CollectFromSaveProperty(collected, element);
            CollectFromPropertyProperty(collected, element);

            foreach (var child in LogicalTreeHelper.GetChildren(element))
            {
                if (child is DependencyObject)
                    CollectRecursive(collected, (DependencyObject)child);
            }
        }

        protected override IEnumerable<ISetting> CollectSettings(object from)
        {
            var collected = new List<ISetting>();

            if (from is DependencyObject)
                CollectRecursive(collected, (DependencyObject) from);

            return collected;
        }
    }
}
